//
// Created on 2025/10/16.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".
#include "common.h"
#include "wav_header.h"
#include <vector>
/**
 * 保存32位浮点WAV文件（更高精度）
 * @param audioData 浮点音频数据
 * @param sampleRate 采样率
 * @param numChannels 声道数
 * @param filename 输出文件名
 * @return 成功返回true，失败返回false
 */
bool saveWavFileFloat32(const std::vector<float> &audioData, int sampleRate, int numChannels,
                        const std::string &filename) {

    if (audioData.empty()) {
        LOGE("音频数据为空");
        return false;
    }

    std::ofstream file(filename, std::ios::binary);
    if (!file.is_open()) {
        LOGE("无法创建文件: %s", filename.c_str());
        return false;
    }

    try {
        const int bitsPerSample = 32;
        const int numSamples = audioData.size() / numChannels;
        const int byteRate = sampleRate * numChannels * bitsPerSample / 8;
        const int blockAlign = numChannels * bitsPerSample / 8;
        const int dataSize = numSamples * numChannels * bitsPerSample / 8;
        const int fileSize = 36 + dataSize;

        // 32位浮点WAV需要特殊的格式代码
        WavHeader header;
        header.chunkSize = fileSize - 8;
        header.numChannels = static_cast<uint16_t>(numChannels);
        header.sampleRate = static_cast<uint32_t>(sampleRate);
        header.byteRate = static_cast<uint32_t>(byteRate);
        header.blockAlign = static_cast<uint16_t>(blockAlign);
        header.bitsPerSample = static_cast<uint16_t>(bitsPerSample);
        header.subchunk2Size = static_cast<uint32_t>(dataSize);
        header.audioFormat = 3; // IEEE Float格式

        // 写入文件头
        file.write(header.chunkId, 4);
        writeLittleEndian(file, header.chunkSize);
        file.write(header.format, 4);
        file.write(header.subchunk1Id, 4);
        writeLittleEndian(file, header.subchunk1Size);
        writeLittleEndian(file, header.audioFormat);
        writeLittleEndian(file, header.numChannels);
        writeLittleEndian(file, header.sampleRate);
        writeLittleEndian(file, header.byteRate);
        writeLittleEndian(file, header.blockAlign);
        writeLittleEndian(file, header.bitsPerSample);
        file.write(header.subchunk2Id, 4);
        writeLittleEndian(file, header.subchunk2Size);

        // 直接写入浮点数据
        file.write(reinterpret_cast<const char *>(audioData.data()), audioData.size() * sizeof(float));

        file.close();
        LOGI("32位浮点WAV文件保存成功: %s", filename.c_str());
        return true;

    } catch (const std::exception &e) {
        LOGE("保存浮点WAV文件失败: %s", e.what());
        file.close();
        return false;
    }
}

#include <algorithm>
#include <cmath>
#include <fstream>
#include <iostream>
#include <vector>

/**
 * 将浮点音频数据保存为16位PCM WAV文件
 * @param audioData 浮点音频数据，范围[-1.0, 1.0]
 * @param sampleRate 采样率
 * @param numChannels 声道数
 * @param filename 输出文件名
 * @return 成功返回true，失败返回false
 */
bool saveWavFile(const std::vector<float> &audioData, int sampleRate, int numChannels, const std::string &filename) {

    if (audioData.empty()) {
        LOGE("音频数据为空");
        return false;
    }

    if (numChannels != 1 && numChannels != 2) {
        LOGE("不支持的声道数: %d", numChannels);
        return false;
    }

    std::ofstream file(filename, std::ios::binary);
    if (!file.is_open()) {
        LOGE("无法创建文件: %s", filename.c_str());
        return false;
    }

    try {
        // 计算WAV文件参数
        const int bitsPerSample = 16;
        const int numSamples = audioData.size() / numChannels;
        const int byteRate = sampleRate * numChannels * bitsPerSample / 8;
        const int blockAlign = numChannels * bitsPerSample / 8;
        const int dataSize = numSamples * numChannels * bitsPerSample / 8;
        const int fileSize = 36 + dataSize;

        // 写入WAV文件头
        WavHeader header;
        header.chunkSize = fileSize - 8;
        header.numChannels = static_cast<uint16_t>(numChannels);
        header.sampleRate = static_cast<uint32_t>(sampleRate);
        header.byteRate = static_cast<uint32_t>(byteRate);
        header.blockAlign = static_cast<uint16_t>(blockAlign);
        header.bitsPerSample = static_cast<uint16_t>(bitsPerSample);
        header.subchunk2Size = static_cast<uint32_t>(dataSize);

        // 写入文件头
        file.write(header.chunkId, 4);
        writeLittleEndian(file, header.chunkSize);
        file.write(header.format, 4);
        file.write(header.subchunk1Id, 4);
        writeLittleEndian(file, header.subchunk1Size);
        writeLittleEndian(file, header.audioFormat);
        writeLittleEndian(file, header.numChannels);
        writeLittleEndian(file, header.sampleRate);
        writeLittleEndian(file, header.byteRate);
        writeLittleEndian(file, header.blockAlign);
        writeLittleEndian(file, header.bitsPerSample);
        file.write(header.subchunk2Id, 4);
        writeLittleEndian(file, header.subchunk2Size);

        // 将浮点数据转换为16位PCM并写入
        for (float sample : audioData) {
            // 限制在[-1.0, 1.0]范围内
            sample = std::max(-1.0f, std::min(1.0f, sample));

            // 转换为16位整数
            int16_t pcmSample = static_cast<int16_t>(sample * 32767.0f);

            // 小端序写入
            file.put(static_cast<char>(pcmSample & 0xFF));
            file.put(static_cast<char>((pcmSample >> 8) & 0xFF));
        }

        file.close();
        LOGI("WAV文件保存成功: %{public}s, 采样数: %{public}d", filename.c_str(), numSamples);
        return true;

    } catch (const std::exception &e) {
        LOGE("保存WAV文件失败: %{public}s", e.what());
        file.close();
        return false;
    }
}

// 实现文件
int SaveAudioToWav(const float *audioData, int dataLength, int sampleRate, int numChannels, const char *filePath) {

    if (!audioData || dataLength <= 0 || !filePath) {
        LOGE("无效的输入参数");
        return -1;
    }

    std::vector<float> audioVector(audioData, audioData + dataLength);

    bool success = saveWavFile(audioVector, sampleRate, numChannels, filePath);

    return success ? 0 : -1;
}

int SaveModelOutputToWav(const float *modelOutput, int outputLength, int sampleRate, const char *filePath) {

    if (!modelOutput || outputLength <= 0 || !filePath) {
        LOGE("无效的模型输出参数");
        return -1;
    }

    std::vector<float> outputVector(modelOutput, modelOutput + outputLength);

    // 假设模型输出是单声道
    bool success = saveWavFile(outputVector, sampleRate, 1, filePath);

    return success ? 0 : -1;
}